package com.etocrm.saas.lib.base.resource.config;

import cn.hutool.crypto.digest.DigestUtil;
import com.etocrm.saas.lib.base.cache.redis.redisson.service.StringRedisClient;
import com.etocrm.saas.lib.base.common.constant.ApiMenuConstant;
import com.etocrm.saas.lib.base.common.result.Result;
import com.etocrm.saas.lib.base.common.vo.UserInfoVO;
import com.etocrm.saas.lib.base.resource.Util.IpAddressUtil;
import com.etocrm.saas.lib.base.resource.cache.UserLoginCacheKey;
import com.etocrm.saas.lib.base.resource.user.ApiUserInfoUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 处理用户登录授权
 */
@Slf4j
public class LoginPermissionInterceptor implements HandlerInterceptor {

    @Autowired
    private StringRedisClient stringRedisClient;
    @Autowired
    private ApiUserInfoUtil apiUserInfoUtil;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler){
        String requestUri = request.getRequestURI();
        if(requestUri.contains(ApiMenuConstant.PUBLIC_KEY_API)){
            log.info("LoginPermissionInterceptor请求路径:" + requestUri);
            //第三方API请求处理
            return thirdPaytyHandler(request,response);
        }
        if(requestUri.contains(ApiMenuConstant.COUPON_ADMIN_API)){
            return loginHandler(request,response);
        }
        return true;
    }

    private boolean loginHandler(HttpServletRequest request, HttpServletResponse response) {
        log.info("web request请求: " + request.getRequestURI());
        return false;
    }

    public boolean thirdPaytyHandler(HttpServletRequest request, HttpServletResponse response){
        String appKey = request.getHeader(ApiMenuConstant.REQUEST_APP_KEY);
        String jwtAuthorization = apiUserInfoUtil.getToken();
        if(StringUtils.isEmpty(appKey)){
            failHandler(request,response,ApiMenuConstant.API_APP_KET_IS_NULL);
            return false;
        }
        if(StringUtils.isEmpty(jwtAuthorization)){
            failHandler(request,response,ApiMenuConstant.API_AUTHORIZATION_IS_NULL);
            return false;
        }
        //检查令牌有效期
        long expire = getExpire(jwtAuthorization);
        if(expire <= 0){
            failHandler(request,response,ApiMenuConstant.API_AUTHORIZATION_TIMEOUT);
            return false;
        }
        //获取用户信息
        UserInfoVO loginUser = apiUserInfoUtil.getLoginUser();
        if(loginUser == null){
            failHandler(request,response,ApiMenuConstant.API_AUTHORIZATION_ERROR);
            return false;
        }
        if(!appKey.equals(loginUser.getAppKey())){
            failHandler(request,response,ApiMenuConstant.API_APP_KEY_ERROR);
            return false;
        }
        if(loginUser.getCheckIp() == 1){
            //获取IP，判断是否一致，不一致则不通过
            String ipAdrress = IpAddressUtil.getIpAdrress(request);
            if(!loginUser.getIp().equals(ipAdrress)){
                failHandler(request,response,ApiMenuConstant.API_IP_ERROR);
                return false;
            }
        }
        return true;
    }

    public void failHandler(HttpServletRequest request, HttpServletResponse response,String error){
        try {
            ObjectMapper objectMapper = new ObjectMapper();
            log.info("请求路径: " + request.getRequestURI());
            log.info("API 拦截异常: " + error);
            response.setCharacterEncoding(ApiMenuConstant.CHARACTER_ENCODING);
            response.setContentType(ApiMenuConstant.CONTENTTYPE);
            response.getWriter().write(objectMapper.writeValueAsString(Result.fail(error)));
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    //查询令牌的有效期
    public long getExpire(String jwtAuthorization){
        String key = DigestUtil.md5Hex(jwtAuthorization);
        Long expire = stringRedisClient.remainTimeToLive(new UserLoginCacheKey(key));
        return expire;
    }

}
